/*
Through-page flow object.
Each component can call methods on the page through the page axis object.
*/
/*
page:{
    name, pageConfig, invokeDataAction, actionTypes, props,init,
    dispatch, dispatchAction, setActionState, getStateValue
}
props:父级页面props
*/

import { useEffect } from "react";
import { Common, PageCommon, Bridge } from 'UtilsCommon';
import EventActions from 'EventActions';
import { EnvConfig } from 'Configs';

const wetRootPath = EnvConfig.getServiceUrl('WebRootPath')();

const pageObj = { lastPageName: '', currentPageName: '' };

class PageAxis {
    constructor(id, parames) {
        this.id = id;
        for (const key in parames) this[key] = parames[key];
        // 接收行为数据state
        this.state = {};
        this.initSet();
        this.init && this.init();
    }

    invoke() {
        return (name) => this[name] ? this[name].bind(this) : function () { };
    }

    receiveActionData(nextState) {
        if (this.actionTypes) {
            let name = ""; let value = 0;
            for (const key in this.actionTypes) {
                name = `receive${key}`;
                value = this.actionTypes[key];
                if (nextState[value] !== undefined && nextState[value] !== this.state[value]) {
                    if (this[name]) this[name](nextState[value]);
                    else if (this.receives[value]) this.receives[value](nextState[value]);
                }
            }
        }
        this.state = nextState;
    }

    receiveActionDataToObject(obj, actionTypes, nextState) {
        obj.state = obj.state || {};
        let name = ""; let value = 0;
        for (const key in actionTypes) {
            name = `receive${key}`;
            value = actionTypes[key];
            if (nextState[value] !== undefined && nextState[value] !== obj.state[value]) {
                if (obj[name]) obj[name](nextState[value]);
                else if (this.receives[value]) this.receives[value](nextState[value]);
            }
        }
        obj.state = nextState;
    }

    refreshPage() {
        let url = this.props.location.pathname + this.props.location.search;
        url = Common.addUrlRandom(url);
        this.toPage(url);
    }

    initSet() {
        this.pageConfig = Common.clone(this.pageConfig);
        this.isComponentPage = this.props.isComponentPage;
        if (this.isComponentPage) {
            this.props.property.pageAxis = this;
        }
        const date = new Date();
        this.startTime = date.getTime();
        this.startTimeString = Common.getDateString(date);

        pageObj.lastPageName = pageObj.currentPageName;
        pageObj.currentPageName = this.name;
        this.lastPageName = pageObj.lastPageName;

        if (this.pageConfig.bodyStyle) this.setBodystyle(this.pageConfig.bodyStyle);

        this.modalDialog = {};

        this.receives = {};
        if (this.pageConfig.eventActions) this.eventActionsConfig = Common.clone(this.pageConfig.eventActions);
        else {
            this.eventActionsConfig = [];
            this.getPropertyEventAction(this.pageConfig);
        }
        if (this.pageConfig.actionOptions) this.actionTypes = this.pageConfig.actionOptions.actionTypes;

        this.pageData = Common.getQueryString();

        // 将pageAxis id赋值到location pageData上
        if (this.props.location && this.props.location.pageData) this.props.location.pageData.pageId = this.id;

        this.eventActions = {};
        for (const key in EventActions) this.eventActions[key] = new EventActions[key]();

        PageCommon.setLoading(true);

        if (!this.isComponentPage) {
            this.initReceives();

            this.setUserName('');

            if (!this.isIndex) {
                Bridge.setReceiveFunction('startShare', (data) => {
                    this.webSocket.send('startShare', data);
                    window.sendSharingData = data;
                });

                Bridge.setReceiveFunction('endShare', () => {
                    this.webSocket.send('endShare');
                    window.sendSharingData = null;
                });
            }

            Bridge.setReceiveFunction('uniteOpen', (data) => {
                this.webSocket.send('uniteOpen', data.File);
            });

            Bridge.setReceiveFunction('uniteClose', (data) => {
                this.webSocket.send('uniteClose', data.File);
            });

            Bridge.setReceiveFunction('videoToBack', (data) => {
                this.webSocket.send('videoToBack', data);
            });

            Bridge.setReceiveFunction('sysncFullScreen', (data) => {
                this.webSocket.send('sysncFullScreen', data);
            });

            Bridge.setReceiveFunction('updateDeviceRole', (data) => {
                this.webSocket.send('updateDeviceRole', data);
                const { IsPresident, DisplayIndex } = data;
                this.visitUser.IsPresident = IsPresident;
                if (DisplayIndex > 0) this.visitUser.DisplayIndex = DisplayIndex;
            });
        }
    }

    setUserName(name) {
        Bridge.jsToNative('setUserName', { Name: name });
    }

    initReceives() {
        this.receiveFunctions = {};
        this.receiveFunctions.toPage = ({ url }) => {
            if (window.isReceShared) return;
            if (this.visitUser && this.visitUser.DeviceType === 1) this.toPage(url, true);
        };

        this.receiveFunctions.replacePage = ({ url }) => {
            if (window.isReceShared) return;
            if (this.visitUser && this.visitUser.DeviceType === 1) this.replacePage(url, true);
        };

        this.receiveFunctions.updateDeviceRole = ({ IsPresident, DisplayIndex, UserId }) => {
            if (this.visitUser && this.visitUser.UserId === UserId) {
                if (this.isMeetingIndex) {
                    this.updateDeviceRole(IsPresident);
                    return;
                }
                this.visitUser.IsPresident = IsPresident;
                if (DisplayIndex > 0) this.visitUser.DisplayIndex = DisplayIndex;
                Bridge.jsToNative('updateDeviceRole', { IsPresident, DisplayIndex });
            }
        };

        this.receiveFunctions.refreshMeetingSubjects = (data) => {
            if (this.visitUser && this.visitUser.DeviceType !== 1) return;

            if (data.IsReset) {
                if (data.IsWelcomePage) {
                    this.replacePage('/welcome.html?MeetingId=' + data.MeetingId + "&backUrl=" + encodeURIComponent('/index.html'), true);
                    return;
                }
                else if (data.IsInSign) {
                    this.replacePage('/userSign.html?MeetingId=' + data.MeetingId + "&backUrl=" + encodeURIComponent('/index.html'), true);
                    return;
                }
            }

            if (this.props.location.pathname.indexOf('meetingSubjectList.html') > 0 && data.MeetingId === this.pageData.MeetingId) {
                this.center_view.reLoad();
            }
            else this.replacePage('/meetingSubjectList.html?MeetingId=' + data.MeetingId, true);
        };

        this.receiveFunctions.startMeeting = this.receiveStartMeeting.bind(this);
        this.receiveFunctions.endMeeting = this.receiveEndMeeting.bind(this);
        this.receiveFunctions.closeBigScreen = () => {
            if (this.isBigScreen) this.exitBigScreen({ isExit: true });
            else Bridge.jsToNative('closeBigScreen');
        };
        this.receiveFunctions.setHeaderStatusName = (data) => {
            this.setHeaderStatusName(data.stateText);
        };
    }

    receiveEndMeeting(data) {
        if (this.visitUser.DeviceType === 3) {
            this.closeToBigScreen && this.closeToBigScreen();
            return;
        }
        if (this.visitUser.DeviceType !== 1 || this.pageData.MeetingId !== data.MeetingId) return;
        Bridge.jsToNative('endMeeting', null, () => {
            this.replacePage('/index.html', true);
        });
    }

    getPropertyEventAction(property) {
        if (property.eventAction && property.eventAction.name) this.eventActionsConfig.push(property.eventAction);
        if (property.properties) {
            property.properties.forEach(p => this.getPropertyEventAction(p));
        }
    }

    setBodystyle(style) {
        style = Common.getStyle(style);
        for (const key in style) {
            document.body.style[key] = style[key];
        }
    }

    setModalDialog(p) {
        p.id = p.id || Common.createGuid();
        this.modalDialog.add && this.modalDialog.add(p);
    }

    showMessage(msg) {
        PageCommon.showMessage(msg);
    }

    getProperty(name) {
        return this.getViewProperty(this.pageConfig, name);
    }

    getRight(name) {
        return !!name;
    }

    getFunction(name) {
        if (!name || !this[name]) return null;
        return (params) => this[name](params);
    }

    getViewProperty(view, name) {
        if (!name) return null;
        if (view.name === name) return view;

        if (view.properties) {
            let v = null;
            for (let i = 0; i < view.properties.length; i++) {
                v = this.getViewProperty2(view.properties[i], name);
                if (v !== null) break;
            }
            if (v != null) return v;
        }

        return this.getDialogViewPrpoerty(name);
    }

    getDialogViewPrpoerty(name) {
        if (this.pageConfig.dialogViews) {
            let v = null;
            for (let i = 0; i < this.pageConfig.dialogViews.length; i++) {
                v = this.getViewProperty2(this.pageConfig.dialogViews[i], name);
                if (v !== null) break;
            }
            if (v != null) return v;
        }
        return null;
    }

    getViewProperty2(view, name) {
        if (view.name === name) return view;

        if (view.properties) {
            let v = null;
            for (let i = 0; i < view.properties.length; i++) {
                v = this.getViewProperty2(view.properties[i], name);
                if (v !== null) break;
            }
            return v;
        }

        return null;
    }

    toPage(url, isReceive) {
        //if (url.match(/#{.*?}/)) url = Common.replaceDataContent(this.pageData, url, true);
        if (url.toLowerCase().indexOf('http') === 0) window.location.href = url;
        else {
            //url = wetRootPath + url;
            //this.props.history.push(url);
            this.replacePage(url, isReceive);
        }
    }

    showLogin({ callback }) {
        const admin_login_dialog = this.getProperty('admin_login_dialog');
        if (admin_login_dialog) admin_login_dialog.pageAxis.show(callback);
    }

    showConfrim(message, callback, okText) {
        const confirm_dialog = this.getProperty('confirm_dialog');
        if (confirm_dialog) confirm_dialog.pageAxis.show(message, callback, okText);
        else PageCommon.confirm(message, callback);
    }

    confirm(msg, onOk) {
        this.showConfrim(msg, onOk);
    }

    toHostPage({ property }) {
        const { name } = property;
        const url = `/${name}.html`;
        if (!this.getIsHost()) {
            this.alert('无权限');
            return;
        }
        this.toMeetingPage(url);
    }

    showMeetingService() {
        const dialog_meeting_service = this.getProperty('dialog_meeting_service');
        if (dialog_meeting_service) dialog_meeting_service.pageAxis.show();
    }

    toMeetingPage(url) {
        const { MeetingId } = this.pageData;
        if (MeetingId) url = Common.addUrlParams(url, 'MeetingId', MeetingId);
        this.replacePage(url);
    }

    replacePage(url, isReceive) {
        if (url.match(/#{.*?}/)) url = Common.replaceDataContent(this.pageData, url, true);
        url = wetRootPath + url;
        const { pathname } = this.props.location;
        const pageName = pathname === '/' ? '/index.html' : pathname;
        const index = url.indexOf('?');
        const urlPath = index > 0 ? url.substring(0, index) : url;

        const queryString = Common.getQueryString(url);
        if (urlPath.indexOf(pageName) >= 0) {
            if (this.reload) this.reload(queryString);
            else {
                this.props.history.replace({
                    pathname,
                    search: url.substring(index),
                    state: null
                });
            }
        }
        else {
            this.props.history.replace(url);
        }
        isReceive && Bridge.jsToNative('changePage');
    }

    goBack(delta, url) {
        if (window.history.state === null || window.history.length === 1 || window.history.state.back === null) this.replacePage(url);
        else if (window.history.length > Math.abs(delta)) window.history.go(delta);
        else this.replacePage(url);
    }

    toBack3() {
        if (this.isMeetingIndex) {
            this.showConfrim('是否退出当前会议？', () => {
                this.replacePage('/index.html');
                Bridge.jsToNative('exitMeeting');
                //this.webSocket.send('exitBigScreen', { userId: this.visitUser.UserId });
                if (this.entityData && this.entityData.IsAsr) {
                    this.endMeetingAsr(this.pageData.MeetingId, this.endMeetingAsr2, this.dispatchAction);
                }
            }, '退出');
        }
        else if (this.pageData.backUrl) {
            this.replacePage(this.pageData.backUrl);
        }
        else if (this.pageConfig.backUrl) {
            this.replacePage(this.pageConfig.backUrl);
        }
        else if (window.userCenterBackUrl) {
            this.replacePage(window.userCenterBackUrl);
            window.userCenterBackUrl = null;
        }
        else this.toBack();
    }

    toUserCenter() {
        if (this.props.location.pathname.indexOf('userCenter.html') > 0) return;
        const { pathname, search } = this.props.location;
        const backUrl = pathname + search;
        if (!window.userCenterBackUrl) window.userCenterBackUrl = backUrl;
        this.replacePage('/userCenter.html?MeetingId=' + this.pageData.MeetingId);
    }

    toBack() {
        if (window.history.state === null || window.history.length === 1 || window.history.state.back === null) this.replacePage('/index.html');
        else window.history.back();
    }

    toLoin() {

    }

    openPage(url) {
        window.open(url);
    }

    alert(msg, duration) {
        PageCommon.alert(msg, duration);
    }

    alertSuccess(msg, onOk, duration) {
        PageCommon.alertSuccess(msg, onOk, duration);
    }

    alertModalSuccess(msg1, msg2, onConfirm) {
        PageCommon.alertModalSuccess(msg1, msg2, onConfirm);
    }

    invokeEventAction(name, obj) {
        const e = this.getEventAction(name);
        if (e != null) e.invoke(obj, e);
    }

    invokeEventAction2(action, obj) {
        const { className, methodName } = action;
        if (this.eventActions[className] && this.eventActions[className][methodName]) {
            this.eventActions[className][methodName](obj, action);
        }
    }

    getEventAction(name) {
        if (this[name]) return { invoke: (a, b) => this[name](a, b) };

        if (this.eventActionsConfig) {
            const e = Common.arrayFirst(this.eventActionsConfig, (f) => f.name === name);
            if (e != null && e.invoke === undefined) {
                e.invoke = (() => {
                    let n1, n2;
                    if (e.type) {
                        const names = e.type.split("/");
                        n1 = names[0];
                        n2 = names[1];
                    }
                    else {
                        n1 = e.className;
                        n2 = e.methodName;
                    }
                    if (this.eventActions[n1] && this.eventActions[n1][n2]) return (a, b) => this.eventActions[n1][n2](a, b);
                    return function () { };
                })();
            }
            return e;
        }
        return null;
    }

    isSuccessProps(res) {
        return res && res.isSuccess !== false;
    }

    addPageVisitTime() {

    }

    addPageAccessStatistics() {
        PageCommon.setLoading(false);
    }

    reSetProperty(property) {
        if (!property.setIsVisible) return;
        property.id = Common.createGuid();
        property.value = null;
        if (property.properties) property.properties.forEach(p => this.reSetProperty(p));
    }

    receiveStartMeeting({ data, serviceInterface, backUrl }) {
        if (this.visitUser.DeviceType !== 1) return;
        const { MeetingId, IsInSign, IsWelcomePage, TimeStatus1 } = data;
        let pageName = 'meetingSubjectList';

        if (IsWelcomePage) pageName = 'welcome';
        else if (IsInSign) pageName = 'userSign';

        const toPage = (pn) => {
            let backUrl2 = '';
            if (pn === 'welcome' || pn === 'userSign') backUrl2 = backUrl;
            const url = `/${pn}.html?MeetingId=${MeetingId}&isStart=true&backUrl=${backUrl2}`;
            this.toPage(url);
        };

        if (TimeStatus1 && (pageName === 'welcome' || pageName === 'userSign')) {
            const { serviceName, actionName } = serviceInterface;
            const id = MeetingId + this.visitUser.UserId;
            const url = `ViewMeetingUserWelcomeSign(${id})`;

            this.dispatchAction(serviceName, actionName, { url }).then(res => {
                if (res && res.isSuccess !== false) {
                    if (pageName === 'welcome' && res.WelcomeId) pageName = 'userSign';
                    if (pageName === 'userSign' && res.UserSignId) pageName = 'meetingSubjectList';
                    toPage(pageName);
                }
            });
        } else toPage(pageName);
    }

    startMeeting2({ property }) {
        const data = property.rowData.data;
        const { MeetingId, TimeStatus2 } = data;
        if (TimeStatus2 && !this.getIsHost()) {
            this.alert('会议未开始');
            return;
        }
        this.toPage(`/meetingSubjectList.html?MeetingId=${MeetingId}`);
    }

    startMeeting(p) {
        const data = p.property ? p.property.rowData.data : p.entityData;
        const { MeetingId, IsInSign, IsWelcomePage, IsAsr } = data;
        let pageName = 'meetingSubjectList';

        if (IsWelcomePage) pageName = 'welcome';
        else if (IsInSign) pageName = 'userSign';

        const isMyMeeting = window.location.href.indexOf('myMeeting.html') > 0;

        let backUrl = '';
        if (pageName === 'welcome' || pageName === 'userSign') backUrl = isMyMeeting ? '/myMeeting.html' : '/bookMeetingList.html';

        const url = `/${pageName}.html?MeetingId=${MeetingId}&isStart=true&backUrl=${backUrl}`;

        const callback = () => {
            this.alertSuccess('所有终端开始会议', () => {
                this.toPage(url);
                this.webSocket.send('toPage', { url });
            }, 1500);
        };
        if (IsAsr) this.startMeetingAsr(MeetingId, callback);
        else callback();
    }

    getIsHost() {
        return this.visitUser.IsPresident;
    }

    onAsrOfflineResult() {
        window.onAsrOfflineResult = (data) => {
            const { text, confid, session_id } = data;
            if (window.asrConfId && window.asrSessions && confid === window.asrConfId) {
                if (window.asrSessions[session_id]) {
                    const { nickname } = window.asrSessions[session_id];
                    const obj = { text, nickname };
                    this.webSocket.send('onAsrOfflineResult', obj);
                    Bridge.jsToNative('onAsrOfflineResult', obj);
                }
            }
        };
    }

    startMeetingAsr(meetingId, callback) {
        const pathQuery = `?MeetingId=${meetingId}`;

        this.dispatchAction('MeetingAsr2Servcie', 'getMeetingAsr', { pathQuery }).then(res => {
            if (res && res.isSuccess !== false) {
                if (!res.IsAsr) {
                    callback();
                    return;
                }

                this.onAsrOfflineResult();

                const curDate = Common.getCurrentDate();
                const meetingTitle = res.Title + '_' + curDate;
                const confId = Common.createGuid();

                window.asrRecorder.load(res.AsrConfig, this.alert, (token) => {
                    window.asrRecorder[meetingId] = true;

                    if (res.NoStoppedConfIds) {
                        this.endMeetingAsr2(res.NoStoppedConfIds, this.dispatchAction);
                    }

                    if (res.IsStarting) {
                        window.asrSessions = JSON.parse(res.Sessions);
                        window.asrConfId = res.ConfId;
                        callback();
                        return;
                    }

                    window.asrRecorder.start(token, confId, res.AudioDevices, res2 => {
                        if (res2.confid) {
                            window.asrRecorder.rename(res2.confid, meetingTitle);

                            window.asrSessions = res2.sessions;
                            window.asrConfId = res2.confid;

                            const MeetingAsr = {
                                StatusText: 'started',
                                StartDate: curDate,
                                MeetingId: meetingId,
                                MeetingRoomId: res.MeetingRoomId,
                                ConfId: confId,
                                Sessions: JSON.stringify(res2.sessions),
                                MeetingTitle: meetingTitle
                            };
                            this.dispatchAction('MeetingAsr2Servcie', 'insertMeetingAsr', { MeetingAsr, pathQuery });

                            callback();
                        }
                    });
                });
            }
            else if (res && res.message) {
                this.alert(res.message);
                window.onAsrOnlineResult = null;
            }
        });
    }

    endMeetingAsr(meetingId, endMeetingAsr2, dispatchAction) {
        if (!window.asrRecorder || !window.asrRecorder[meetingId]) return;

        const pathQuery = `?MeetingId=${meetingId}`;

        dispatchAction('MeetingAsr2Servcie', 'getNoStoppedMeetingAsr', { isCanDestory: true, pathQuery }).then(res => {
            if (res && res.isSuccess !== false) {
                window.asrRecorder[meetingId] = false;
                endMeetingAsr2(res.NoStoppedConfIds, dispatchAction);
            }
        });
    }

    endMeetingAsr2(ids, dispatchAction) {
        ids.forEach(id => {
            window.asrRecorder.stop(id, (res) => {
                window.asrRecorder.summary(res.confid);

                const pathQuery = `(${res.confid})`;
                const MeetingAsr = {
                    StatusText: 'stopped',
                    EndDate: Common.getCurrentDate()
                };
                dispatchAction('MeetingAsr2Servcie', 'updateMeetingAsr', { MeetingAsr, pathQuery });
            });
        });
    }
}

const _PageAxises = {};

const usePageAxis = (id, name, pageConfig, invokeDataAction, actionTypes, dispatch, props,
    dispatchAction, setActionState, getActionState, getStateValue, init) => {
    useEffect(() => () => {
        const pageAxis = _PageAxises[id];
        if (pageAxis) {
            pageAxis.isDestroy = true;
            pageAxis.addPageVisitTime();
            delete _PageAxises[id];
        }
    }, [id]);

    if (!pageConfig) return null;

    if (!_PageAxises[id]) {
        _PageAxises[id] = new PageAxis(id, {
            name,
            pageConfig,
            invokeDataAction,
            actionTypes,
            dispatch,
            props,
            dispatchAction,
            setActionState,
            getActionState,
            getStateValue,
            init
        });

        _PageAxises[id].getStateValue = getStateValue;
    }

    return _PageAxises[id];
};

usePageAxis.getPageAxis = (id) => _PageAxises[id];

export default usePageAxis;